/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package gtree;

import java.util.ArrayList;

/**
 *
 * @author grostirolla
 */
public class Tree {

    private Node root;
    private int count;
    private int DEFROOTX = 100;
    private int DEFROOTY = 100;
    private int SPACEX = 250;
    private int SPACEY = 150;
    private double dimensionX = 0;
    private double dimensionY = 0;

    public double getDimensionX() {
        return dimensionX;
    }

    public double getDimensionY() {
        return dimensionY;
    }

    public Tree(String element) {
        root = new Node(null, element, DEFROOTX, DEFROOTY);
        this.count = 1;
    }

    public Tree(String element, double rootX, double rootY) {
        root = new Node(null, element, rootX, rootY);
        this.count = 1;
    }

    public Position root() {
        return this.root;
    }

    public Position parent(Position pos) throws Exception {
        Node n = (Node) pos;
        if (!isRoot(n)) {
            return (Position) n.getParentNode();
        } else {
            throw new Exception("root node");
        }
    }

    public ArrayList<Position> children(Position pos) throws Exception {
        Node n = (Node) pos;
        if (n.getChildren() != null) {
            ArrayList<Position> positions = new ArrayList<Position>();
            for (Node i : n.getChildren()) {
                positions.add(i);
            }
            return positions;
        } else {
            throw new Exception("no children");
        }
    }

    public boolean isRoot(Position pos) {
        if ((Node) pos == root) {
            return true;
        } else {
            return false;
        }
    }

    public boolean isExternal(Position pos) {
        Node n = (Node) pos;
        try {
            if (n.getChildren().size() > 0) {
                return false;
            } else {
                return true;
            }
        } catch (Exception e) {
            return true;
        }
    }

    public boolean isInternal(Position pos) {
        Node n = (Node) pos;
        try {
            n.getChildren();
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public int size() {
        return this.count;
    }

    public ArrayList<String> elements() {
        Node n = root;
        ArrayList<String> elements = new ArrayList<String>();
        recGetElements(n, elements);
        return elements;

    }

    public ArrayList<Position> positions() {
        Node n = root;
        ArrayList<Position> positions = new ArrayList<Position>();
        recGetPositions(n, positions);
        return positions;
    }

    public void swapElements(Position p1, Position p2) {
        String aux;
        aux = ((Node) p1).getElement();
        ((Node) p1).setElement(((Node) p2).getElement());
        ((Node) p2).setElement(aux);

    }

    public String replaceElement(Position pos, String element) {
        Node n = (Node) pos;
        String previous = n.getElement();
        n.setElement(element);
        return previous;
    }

    public Position addChild(Position pos, String element) {
        /*
         * Node n = (Node) pos; Node child = new Node(n, element);
         * ArrayList<Node> children = n.getChildren(); children.add(child);
         * n.setChildren(children); count++; return child;
         */
        //System.out.println("PARENT OF "+((Node)pos)+" is "+((Node)pos).getParentNode().getClass());
        Node n = (Node) pos;
        int multiplier = n.getChildren().size();
        if ((n.getX() + SPACEX) > dimensionX) {
            dimensionX = n.getX() + SPACEX;
        }
        if ((n.getY() + SPACEY * multiplier) > dimensionY) {
            dimensionY = n.getY() + SPACEY * multiplier;
        }
        Node child = new Node(n, element, n.getX() + SPACEX, n.getY() + SPACEY * multiplier);
        ArrayList<Node> children = n.getChildren();
        children.add(child);
        n.setChildren(children);
        count++;
        return child;
    }

    public void removeExternal(Position pos) throws Exception {
        Node n = (Node) pos;
        Node father = n.getParentNode();
        if (isExternal(pos) && !isRoot(pos)) {
            for (int i = 0; i < father.getChildren().size(); i++) {
                if (father.getChildren().get(i) == n) {
                    father.getChildren().remove(father.getChildren().get(i));
                    count--;
                    break;
                }
            }
        } else {
            throw new Exception("This node is not External");
        }
    }

    private ArrayList<String> recGetElements(Node n, ArrayList<String> array) {
        array.add(n.getElement());
        if (n.getChildren().size() > 0) {
            for (int i = 0; i < n.getChildren().size(); i++) {
                recGetElements(n.getChildren().get(i), array);
            }
        }
        return array;
    }

    private ArrayList<Position> recGetPositions(Node n, ArrayList<Position> array) {
        array.add((Position) n);
        if (n.getChildren().size() > 0) {
            for (int i = 0; i < n.getChildren().size(); i++) {
                recGetPositions(n.getChildren().get(i), array);
            }
        }
        return array;
    }
}
